﻿using Server.Business.proto;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Server.TCP
{
    public abstract class MappingColumn
    {
        public int Index { get; set; }
        public string Column { get; set; }
        public string Property { get; set; }

        private string Filtervalue(string value)
        {
            return value.Trim();
        }

        public abstract void SetValue(PropertyInfo pi, object instance, string value);
    }

    public class PrimitiveTypeColumn : MappingColumn
    {
        public override void SetValue(PropertyInfo pi, object instance, string value)
        {
            if (pi.PropertyType == typeof(string))
            {
                pi.SetValue(instance, value, null);
            }
            else if (pi.PropertyType == typeof(int))
            {
                int intValue;
                if (int.TryParse(value, out intValue))
                    pi.SetValue(instance, intValue, null);
            }
            else if (pi.PropertyType == typeof(double))
            {
                double doubleValue;
                if (double.TryParse(value, out doubleValue))
                    pi.SetValue(instance, doubleValue, null);
            }
        }
    }

    public class RefColumn : MappingColumn
    {
        public IEnumerable<ResItem> Items { get; set; }

        public override void SetValue(PropertyInfo pi, object instance, string value)
        {
            ResItem item = (from r in Items
                            where r.ItemName == value
                            select r).FirstOrDefault();

            if(item != null)
                pi.SetValue(instance, item.ItemID, null);
        }
    }

    public class ImageColumn : MappingColumn
    {
        private enum PictureType
        {
            PNG = 1,
            BMP = 2,
            JPG = 3
        }

        private static Dictionary<string, ImageFormat> _pictureTypes;

        static ImageColumn()
        {
            _pictureTypes = new Dictionary<string, ImageFormat>();
            _pictureTypes["png"] = ImageFormat.Png;
            _pictureTypes["jpg"] = ImageFormat.Jpeg;
            _pictureTypes["jpeg"] = ImageFormat.Jpeg;
        }

        public string ImageFolder { get; set; }
        public ImageFile ImageFile { get; set; }
        public int[] ZoomLevels { get; set; }

        public override void SetValue(PropertyInfo pi, object instance, string value)
        {
            int extStartIndex = ImageFile.Name.LastIndexOf('.');
            string ext = ImageFile.Name.Substring(extStartIndex + 1).ToLower();
            string prefixName = ImageFile.Name.Substring(0, extStartIndex);

            string localName = ImageFile.Name;
            if (ext == "bmp")
            {
                string originalImageUrl = Path.Combine(ImageFolder, localName);
                if (!File.Exists(originalImageUrl))
                {
                    using (MemoryStream ms = new MemoryStream(ImageFile.File))
                    {
                        Image bmpImage = Image.FromStream(ms);
                        localName = prefixName + ".jpg";
                        bmpImage.Save(Path.Combine(ImageFolder, localName), ImageFormat.Jpeg);

                        foreach (int zoolLevel in ZoomLevels)
                        {
                            string resizedUrl = Path.Combine(ImageFolder, zoolLevel.ToString(), localName);
                            if (!File.Exists(resizedUrl))
                            {
                                Image resized = ResizeImage(bmpImage, new Size(zoolLevel, zoolLevel));
                                resized.Save(resizedUrl, ImageFormat.Jpeg);
                                resized.Dispose();
                            }
                        }
                    }
                }
                else
                {
                    using (FileStream fs = File.OpenRead(originalImageUrl))
                    {
                        Image bmpImage = Image.FromStream(fs);
                        localName = prefixName + ".jpg";
                        bmpImage.Save(Path.Combine(ImageFolder, localName), ImageFormat.Jpeg);

                        foreach (int zoolLevel in ZoomLevels)
                        {
                            string resizedUrl = Path.Combine(ImageFolder, zoolLevel.ToString(), localName);
                            if (!File.Exists(resizedUrl))
                            {
                                Image resized = ResizeImage(bmpImage, new Size(zoolLevel, zoolLevel));
                                resized.Save(resizedUrl, ImageFormat.Jpeg);
                                resized.Dispose();
                            }
                        }
                    }
                }


            }
            else
            {
                string originalImageUrl = Path.Combine(ImageFolder, localName);
                if (!File.Exists(originalImageUrl))
                {
                    using (FileStream fs = File.Create(originalImageUrl))
                    {
                        fs.Write(ImageFile.File, 0, ImageFile.File.Length);
                        fs.Flush();

                        Image original = Image.FromStream(fs);
                        foreach (int zoolLevel in ZoomLevels)
                        {
                            Image resized = ResizeImage(original, new Size(zoolLevel, zoolLevel));
                            string resizedRrl = Path.Combine(ImageFolder, zoolLevel.ToString(), localName);
                            resized.Save(resizedRrl, _pictureTypes[ext]);
                            resized.Dispose();
                        }
                    }
                }
                else
                {
                    using (FileStream fs = File.OpenRead(originalImageUrl))
                    {
                        Image original = Image.FromStream(fs);
                        foreach (int zoolLevel in ZoomLevels)
                        {
                            string resizedUrl = Path.Combine(ImageFolder, zoolLevel.ToString(), localName);
                            if (!File.Exists(resizedUrl))
                            {
                                Image resized = ResizeImage(original, new Size(zoolLevel, zoolLevel));
                                resized.Save(resizedUrl, _pictureTypes[ext]);
                                resized.Dispose();
                            }
                        }
                    }
                }
            }

            pi.SetValue(instance, localName, null);
        }

        private Image ResizeImage(Image image, Size size, bool preserveAspectRatio = true)
        {
            int newWidth;
            int newHeight;
            if (preserveAspectRatio)
            {
                int originalWidth = image.Width;
                int originalHeight = image.Height;
                float percentWidth = (float)size.Width / (float)originalWidth;
                float percentHeight = (float)size.Height / (float)originalHeight;
                float percent = percentHeight < percentWidth ? percentHeight : percentWidth;
                newWidth = (int)(originalWidth * percent);
                newHeight = (int)(originalHeight * percent);
            }
            else
            {
                newWidth = size.Width;
                newHeight = size.Height;
            }
            Image newImage = new Bitmap(newWidth, newHeight);
            using (Graphics graphicsHandle = Graphics.FromImage(newImage))
            {
                graphicsHandle.InterpolationMode = InterpolationMode.HighQualityBicubic;
                graphicsHandle.DrawImage(image, 0, 0, newWidth, newHeight);
            }
            return newImage;

            //Image original = Image.FromFile(@"D:\Test\test.jpg");
            //Image resized = ResizeImage(original, new Size(50, 50));
            //resized.Save(@"D:\Test\resize.jpg", ImageFormat.Jpeg);
        }
    }
}
